package id.co.rho.scoring.cid.client.mvc.scoringmodel;

import id.co.rho.scoring.cid.client.helper.Resources;
import id.co.rho.scoring.cid.client.model.CriteriaTree;
import id.co.rho.scoring.cid.client.mvc.AppView;
import id.co.rho.scoring.cid.client.utils.CommonUtils;
import id.co.rho.scoring.cid.client.utils.Folder;

import java.util.Arrays;
import java.util.List;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelIconProvider;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.event.WindowListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.extjs.gxt.ui.client.widget.treegrid.EditorTreeGrid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGridSelectionModel;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

public class ScoringModelUIWeb implements ScoringModelUI{
	private Folder model;
	private TreeStore<ModelData> store;
	private ColumnConfig criteriaName, criteriaNumber, criteriaRank,
			criteriaWeight, criteriaType, id, parentId;
	private ColumnModel cm;
	private TreeGrid<ModelData> tree;
	public ContentPanel cp;
	private ToolBar toolbar;
	private Button btnAdd, btnEdit, btnAddMain;
	private Button btnSave, btnCancel, btnDelete;
	private Menu contextMenu;
	private MenuItem addMainCriteria;
	private MenuItem addCriteria;
	private MenuItem editCriteria;
	private MenuItem addQuestion;
	private MenuItem addAnswer;
	private MenuItem deleteCriteria;
	private Window window;
	public Long modelId;
	private boolean addData;
	private String tipe;
	TextField<String> txtName;
	TextField<String> txtNumber;
	TextField<String> txtRank;
	TextField<String> txtWeight;
	SimpleComboBox<String> cboType;
	private Long idParent;
	private Long idCriteria;

	@Override
	public void initialize() {

		model = new Folder();

		store = new TreeStore<ModelData>();
		store.add(model.getChildren(), true);

		TreeGridCellRenderer<ModelData> labelColumnRenderer = new TreeGridCellRenderer<ModelData>() {
			@Override
			public Object render(ModelData modelData, String property,
					ColumnData config, int rowIndex, int colIndex,
					ListStore<ModelData> modelDataListStore,
					Grid<ModelData> modelDataGrid) {

				Object result = super.render(modelData, property, config,
						rowIndex, colIndex, modelDataListStore, modelDataGrid);
				config.style = config.style.replaceAll(
						"background-color:[#1-9a-zA-Z]+;", "");
				if (!CommonUtils.isEmpty(modelData.<String> get("changeState"))) {
					if (modelData.<String> get("changeState").equalsIgnoreCase(
							"edit")) {
						config.style = config.style
								+ "background-color:#FFFF00;";
					} else if (modelData.<String> get("changeState")
							.equalsIgnoreCase("new")) {
						config.style = config.style
								+ "background-color:#57E964;";
					} else if (modelData.<String> get("changeState")
							.equalsIgnoreCase("delete")) {
						config.style = config.style
								+ "background-color:#FF0000;";
					}
				}

				return result;
			}
		};

		criteriaName = new ColumnConfig("criteriaName", "Name", 100);
		criteriaName.setRenderer(labelColumnRenderer);

		criteriaNumber = new ColumnConfig("criteriaNumber", "Number", 100);
		criteriaRank = new ColumnConfig("criteriaRank", "Rank", 100);
		criteriaWeight = new ColumnConfig("criteriaWeight", "Weight", 100);
		criteriaType = new ColumnConfig("criteriaType", "Type", 100);

		id = new ColumnConfig("id", "Id", 100);
		parentId = new ColumnConfig("parentId", "Parent", 100);
		parentId.setHidden(true);
		id.setHidden(true);
		cm = new ColumnModel(Arrays.asList(criteriaName, criteriaNumber,
				criteriaRank, criteriaWeight, criteriaType, id, parentId));
		toolbar = new ToolBar();
		btnAdd = new Button("Add Child");
		btnEdit = new Button("Edit");
		btnAddMain = new Button("Add Main Criteria");
		btnSave = new Button("Save");
		btnCancel = new Button("Cancel");
		btnDelete = new Button("Delete");
		toolbar.add(btnSave);
		toolbar.add(btnCancel);
		toolbar.add(btnDelete);
		// toolbar.add(btnEdit);

		cp = new ContentPanel();
		cp.setBodyBorder(false);
		cp.setHeading("Scoring Model");
		cp.setButtonAlign(HorizontalAlignment.CENTER);
		cp.setLayout(new FitLayout());
		cp.setFrame(true);
		cp.setSize(600, 300);

		tree = new EditorTreeGrid<ModelData>(store, cm);
		tree.setBorders(true);
		tree.setIconProvider(new ModelIconProvider<ModelData>() {
			@Override
			public AbstractImagePrototype getIcon(final ModelData model) {
				AbstractImagePrototype result = Resources.ICONS.textCriteria();
				if (!CommonUtils.isEmpty(model.<String> get("criteriaType"))) {
					if (model.<String> get("criteriaType").equalsIgnoreCase(
							"answer")) {
						result = Resources.ICONS.answer();
					} else if (model.<String> get("criteriaType")
							.equalsIgnoreCase("question")) {
						result = Resources.ICONS.question();
					}
				}

				return result;
			}
		});
		tree.setSize(400, 400);
		tree.setAutoExpandColumn("criteriaName");
		tree.setTrackMouseOver(false);
		tree.setSelectionModel(new TreeGridSelectionModel<ModelData>());
		tree.expandAll();
		contextMenu = new Menu();
		addQuestion = new MenuItem();
		addQuestion.setText("Add Question");
		addQuestion.setIcon(Resources.ICONS.question());
		addQuestion.addSelectionListener(new SelectionListener<MenuEvent>() {
			@Override
			public void componentSelected(MenuEvent ce) {
				tipe = "Add";
				idParent = tree.getSelectionModel().getSelectedItem().get("id");
				clearText();
				cboType.setSimpleValue("QUESTION");
				window.show();
			}
		});

		addAnswer = new MenuItem();
		addAnswer.setText("Add Answer");
		addAnswer.setIcon(Resources.ICONS.answer());
		addAnswer.addSelectionListener(new SelectionListener<MenuEvent>() {
			@Override
			public void componentSelected(MenuEvent ce) {
				tipe = "Add";
				idParent = tree.getSelectionModel().getSelectedItem().get("id");
				clearText();
				cboType.setSimpleValue("ANSWER");
				window.show();
			}
		});

		addMainCriteria = new MenuItem();
		addMainCriteria.setText("Add Main Criteria");
		addMainCriteria.setIcon(Resources.ICONS.textCriteria());
		addMainCriteria
				.addSelectionListener(new SelectionListener<MenuEvent>() {
					@Override
					public void componentSelected(MenuEvent ce) {
						tipe = "Main";
						clearText();
						cboType.setSimpleValue("CRITERIA");
						window.show();
					}
				});

		addCriteria = new MenuItem();
		addCriteria.setText("Add Criteria");
		addCriteria.setIcon(Resources.ICONS.textCriteria());
		addCriteria.addSelectionListener(new SelectionListener<MenuEvent>() {
			@Override
			public void componentSelected(MenuEvent ce) {
				tipe = "Add";
				idParent = tree.getSelectionModel().getSelectedItem().get("id");
				clearText();
				cboType.setSimpleValue("CRITERIA");
				window.show();
			}
		});
		editCriteria = new MenuItem();
		editCriteria.setText("Edit");
		editCriteria.setIcon(Resources.ICONS.edit());
		editCriteria.addSelectionListener(new SelectionListener<MenuEvent>() {

			@Override
			public void componentSelected(MenuEvent ce) {
				tipe = "Edit";
				idCriteria = tree.getSelectionModel().getSelectedItem()
						.get("id");
				clearText();
				if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaName") != null)
					txtName.setValue(tree.getSelectionModel().getSelectedItem()
							.get("criteriaName").toString());
				if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaNumber") != null)
					txtNumber
							.setValue(tree.getSelectionModel()
									.getSelectedItem().get("criteriaNumber")
									.toString());
				if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaRank") != null)
					txtRank.setValue(tree.getSelectionModel().getSelectedItem()
							.get("criteriaRank").toString());
				if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaWeight") != null)
					txtWeight
							.setValue(tree.getSelectionModel()
									.getSelectedItem().get("criteriaWeight")
									.toString());
				if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaType") != null)
					cboType.setSimpleValue(tree.getSelectionModel()
							.getSelectedItem().get("criteriaType").toString());
				idParent = Long.valueOf(tree.getSelectionModel()
						.getSelectedItem().get("parentId").toString());
				window.show();

			}
		});

		deleteCriteria = new MenuItem();
		deleteCriteria.setText("Delete");
		deleteCriteria.setIcon(Resources.ICONS.delete());

		deleteCriteria.addSelectionListener(new SelectionListener<MenuEvent>() {
			public void componentSelected(MenuEvent ce) {
				ModelData selected = tree.getSelectionModel().getSelectedItem();

				if (isNewRecord(selected)) {
					store.remove(selected);
				} else {
					store.getRecord(selected).set("changeState", "delete");
					store.setMonitorChanges(true);
					if (store.getChildCount(selected) > 0) {
						List<ModelData> models = store.getChildren(selected);
						for (ModelData data : models) {
							if (isNewRecord(data)) {
								store.remove(data);
							} else {
								store.getRecord(data).set("changeState",
										"delete");
								store.setMonitorChanges(true);
								childrenDeletedFlag(data);
							}

						}
					}

				}
			}
		});
		tree.addListener(Events.ContextMenu, new Listener<BaseEvent>() {

			@Override
			public void handleEvent(BaseEvent be) {
				if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaType").toString()
						.equalsIgnoreCase("QUESTION")) {
					contextMenu.removeAll();
					contextMenu.add(addAnswer);
					contextMenu.add(editCriteria);
					contextMenu.add(deleteCriteria);
				} else if (tree.getSelectionModel().getSelectedItem()
						.get("criteriaType").toString()
						.equalsIgnoreCase("ANSWER")) {
					contextMenu.removeAll();
					contextMenu.add(editCriteria);
					contextMenu.add(deleteCriteria);
				} else {
					contextMenu.removeAll();
					contextMenu.add(addMainCriteria);
					contextMenu.add(addCriteria);
					contextMenu.add(addQuestion);
					contextMenu.add(editCriteria);
					contextMenu.add(deleteCriteria);
				}
			}
		});
		tree.setContextMenu(contextMenu);
		cp.add(tree);
		initWindow();
	}
	
	@Override
	public void childrenDeletedFlag(ModelData model) {
		if (store.getChildCount(model) > 0) {
			List<ModelData> models = store.getChildren(model);
			for (ModelData data : models) {
				if (isNewRecord(data)) {
					store.remove(data);
				} else {
					store.getRecord(data).set("changeState", "delete");
					childrenDeletedFlag(data);
				}

			}
		}
	}

	@Override
	public Boolean isNewRecord(ModelData data) {
		Boolean result = Boolean.FALSE;
		if (!CommonUtils.isEmpty(data.<String> get("changeState"))) {
			if (data.<String> get("changeState").equalsIgnoreCase("new")) {
				result = Boolean.TRUE;
			}
		}
		return result;
	}

	private void clearText() {
		txtName.setValue("");
		txtNumber.setValue("");
		txtRank.setValue("0");
		txtWeight.setValue("0");
	}

	private Boolean changes(ModelData selected) {
		Boolean result = false;
		String strName = "";
		String strNumber = "";
		String strRank = "0";
		String strWeight = "0";
		String strType = "";
		if ((!CommonUtils.isEmpty(selected.<String> get("criteriaName")))) {
			strName = selected.get("criteriaName").toString();
		}

		if (selected.get("criteriaNumber") != null) {
			strNumber = selected.get("criteriaNumber").toString();
		}

		if (selected.get("criteriaRank") != null) {
			strRank = selected.get("criteriaRank").toString();
		}

		if (selected.get("criteriaWeight") != null) {

			strWeight = selected.get("criteriaWeight").toString();
		}

		if ((!CommonUtils.isEmpty(selected.<String> get("criteriaType")))) {
			strType = selected.get("criteriaType").toString();
		}

		if (!strName.equalsIgnoreCase(txtName.getValue())) {
			result = true;
		} else if (!strNumber.equalsIgnoreCase(txtNumber.getValue())) {
			result = true;
		} else if (!strRank.equalsIgnoreCase(txtRank.getValue())) {
			result = true;
		} else if (!strWeight.equalsIgnoreCase(txtWeight.getValue())) {
			result = true;
		} else if (!strType.equalsIgnoreCase(cboType.getSimpleValue())) {
			result = true;
		}
		return result;
	}

	@Override
	public void initWindow() {
		window = new Window();
		window.setSize(350, 230);
		window.setPlain(true);
		window.setModal(true);
		window.setBlinkModal(true);
		window.setHeading("Scoring Model");
		window.setLayout(new FitLayout());
		window.addWindowListener(new WindowListener() {
			@Override
			public void windowHide(WindowEvent we) {
				Button open = we.getWindow().getData("open");
				open.focus();
			}
		});

		FieldSet fsInput = new FieldSet();
		FormLayout formLayout = new FormLayout();
		formLayout.setLabelAlign(FormPanel.LabelAlign.LEFT);

		fsInput = new FieldSet();
		fsInput.setLayout(formLayout);

		txtName = new TextField<String>();
		txtName.setFieldLabel("Name");
		txtName.setWidth("500px");
		txtNumber = new TextField<String>();
		txtNumber.setFieldLabel("Number");
		txtRank = new TextField<String>();
		txtRank.setFieldLabel("Rank");
		txtWeight = new TextField<String>();
		txtWeight.setFieldLabel("Weight");
		cboType = new SimpleComboBox<String>();
		cboType.setFieldLabel("Type");

		fsInput.add(txtName);
		fsInput.add(txtNumber);
		fsInput.add(txtRank);
		fsInput.add(txtWeight);
		fsInput.add(cboType);

		cboType.add("CRITERIA");
		cboType.add("QUESTION");
		cboType.add("ANSWER");

		LayoutContainer lcButton = new LayoutContainer();
		lcButton.setStyleAttribute("margin-top", "10px");
		lcButton.setLayout(new HBoxLayout());
		fsInput.add(lcButton);
		Button btnSave = new Button();
		btnSave.setStyleAttribute("padding-left", "5px");
		btnSave.setText("Save");
		Button btnCancel = new Button();
		btnCancel.setStyleAttribute("padding-left", "5px");
		btnCancel.setText("Cancel");
		lcButton.add(btnSave);
		lcButton.add(btnCancel);
		window.add(fsInput);
		btnCancel.addSelectionListener(new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				window.hide();

			}
		});

		btnSave.addSelectionListener(new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				if (tipe.equalsIgnoreCase("Edit")) {

					ModelData selected = tree.getSelectionModel()
							.getSelectedItem();
					if (changes(selected)) {
						store.getRecord(selected).set("criteriaName",
								txtName.getValue());
						store.getRecord(selected).set("criteriaNumber",
								txtNumber.getValue());
						store.getRecord(selected).set("criteriaRank",
								txtRank.getValue());
						store.getRecord(selected).set("criteriaWeight",
								txtWeight.getValue());
						store.getRecord(selected).set("criteriaType",
								cboType.getSimpleValue());

						store.getRecord(selected).set("changeState", "edit");
						store.setMonitorChanges(true);
						cp.layout();
						tree.expandAll();
					}
					window.hide();
				} else if (tipe.equalsIgnoreCase("add")) {
					CriteriaTree critTree = new CriteriaTree();
					critTree.set("criteriaName", txtName.getValue());
					critTree.set("criteriaNumber", txtNumber.getValue());
					critTree.set("criteriaRank", txtRank.getValue());
					critTree.set("criteriaWeight", txtWeight.getValue());
					critTree.set("criteriaType", cboType.getSimpleValue());
					critTree.set("changeState", "new");

					List<ModelData> children = store.getChildren(tree
							.getSelectionModel().getSelectedItem());
					int latestPosition = 0;
					for (ModelData modelData : children) {
						if (Integer.parseInt(modelData.get("position")
								.toString()) > latestPosition) {
							latestPosition = Integer.parseInt(modelData.get(
									"position").toString());
						}
					}
					latestPosition++;
					critTree.set("position", String.valueOf(latestPosition));
					if (tree.getSelectionModel().getSelectedItem()
							.get("parentId") == null) {
						critTree.set("parentId", 0);
					} else {
						critTree.set("parentId", tree.getSelectionModel()
								.getSelectedItem().get("parentId"));
					}

					store.add(tree.getSelectionModel().getSelectedItem(),
							critTree, false);
					store.setMonitorChanges(true);
					cp.layout();
					tree.expandAll();
					window.hide();
				} else if (tipe.equalsIgnoreCase("main")) {
					CriteriaTree critTree = new CriteriaTree();
					critTree.set("criteriaName", txtName.getValue());
					critTree.set("criteriaNumber", txtNumber.getValue());
					critTree.set("criteriaRank", txtRank.getValue());
					critTree.set("criteriaWeight", txtWeight.getValue());
					critTree.set("criteriaType", cboType.getSimpleValue());
					critTree.set("changeState", "new");

					List<ModelData> children = model.getChildren();
					int latestPosition = 0;
					for (ModelData modelData : children) {
						if (Integer.parseInt(modelData.get("position")
								.toString()) > latestPosition) {
							latestPosition = Integer.parseInt(modelData.get(
									"position").toString());
						}
					}
					latestPosition++;
					critTree.set("position", String.valueOf(latestPosition));
					store.add(critTree, false);
					cp.layout();
					tree.expandAll();
					window.hide();
				}
			}
		});

	}

	@Override
	public void show() {

		BorderLayoutData borderlayoutDataNorth = new BorderLayoutData(
				LayoutRegion.NORTH);
		borderlayoutDataNorth.setSize(25);
		ContentPanel centerPanel = (ContentPanel) Registry
				.get(AppView.CENTER_PANEL);
		store.setMonitorChanges(false);

		centerPanel.removeAll();
		centerPanel.setLayout(new BorderLayout());
		centerPanel.add(toolbar, borderlayoutDataNorth);
		centerPanel.add(cp, new BorderLayoutData(LayoutRegion.CENTER));

		centerPanel.layout();
		tree.expandAll();
	}

	@Override
	public void setModel(Folder model) {
		this.model = model;
		this.tree.expandAll();
		store.removeAll();
		store.add(model.getChildren(), true);
		cp.layout();
		tree.expandAll();
	}

	@Override
	public TreeGrid<ModelData> getTree() {
		return tree;
	}

	@Override
	public Button getBtnAdd() {
		return btnAdd;
	}

	@Override
	public Button getBtnAddMain() {
		return btnAddMain;
	}

	@Override
	public Button getBtnEdit() {
		return btnEdit;
	}

	@Override
	public MenuItem getAddMainCriteria() {
		return addMainCriteria;
	}
	
	@Override
	public MenuItem getAddCriteria() {
		return addCriteria;
	}

	@Override
	public MenuItem getEditCriteria() {
		return editCriteria;
	}

	@Override
	public Button getBtnSave() {
		return btnSave;
	}

	@Override
	public Button getBtnCancel() {
		return btnCancel;
	}

	@Override
	public Button getBtnDelete() {
		return btnDelete;
	}

	@Override
	public Long getModelId() {
		return modelId;
	}

	@Override
	public void setModelId(Long modelId) {
		this.modelId = modelId;
	}
	
	

}
